{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "# LLM Actions and Structure Messages\n",
        "\n",
        "## Review\n",
        "\n",
        "We built a simple graph with nodes, normal edges, and conditional edges.\n",
        "\n",
        "## Goals\n",
        "\n",
        "Now, let's understand the power of Actions with AI Models and before that structure our prompts."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Messages\n",
        "\n",
        "Chat models can use [`messages`](https://python.langchain.com/v0.2/docs/concepts/#messages), which capture different roles within a conversation.\n",
        "\n",
        "LangChain supports various message types, including `HumanMessage`, `AIMessage`, `SystemMessage`, and `ToolMessage`.\n",
        "\n",
        "These represent a message from the user, from chat model, for the chat model to instruct behavior, and from a tool call.\n",
        "\n",
        "Let's create a list of messages.\n",
        "\n",
        "Each message can be supplied with a few things:\n",
        "\n",
        "* `content` - content of the message\n",
        "* `name` - optionally, a message author\n",
        "* `response_metadata` - optionally, a dict of metadata (e.g., often populated by model provider for `AIMessages`)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 13,
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "==================================\u001b[1m Ai Message \u001b[0m==================================\n",
            "Name: Model\n",
            "\n",
            "So you said you were researching ocean mammals?\n",
            "================================\u001b[1m Human Message \u001b[0m=================================\n",
            "Name: Lance\n",
            "\n",
            "Yes, that's right.\n",
            "==================================\u001b[1m Ai Message \u001b[0m==================================\n",
            "Name: Model\n",
            "\n",
            "Great, what would you like to learn about.\n",
            "================================\u001b[1m Human Message \u001b[0m=================================\n",
            "Name: Lance\n",
            "\n",
            "I want to learn about the best place to see Orcas in the US.\n"
          ]
        }
      ],
      "source": [
        "from pprint import pprint\n",
        "from langchain_core.messages import AIMessage, HumanMessage, SystemMessage\n",
        "\n",
        "messages = [AIMessage(content=f\"So you said you were researching ocean mammals?\", name=\"Model\")]\n",
        "messages.append(HumanMessage(content=f\"Yes, that's right.\",name=\"Lance\"))\n",
        "messages.append(AIMessage(content=f\"Great, what would you like to learn about.\", name=\"Model\"))\n",
        "messages.append(HumanMessage(content=f\"I want to learn about the best place to see Orcas in the US.\", name=\"Lance\"))\n",
        "\n",
        "for m in messages:\n",
        "    m.pretty_print()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "From now let's use HumanMessage to pass our Prompt to Model"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "from google.colab import userdata\n",
        "gemini_api_key = userdata.get('GEMINI_API_KEY')\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 16,
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Note: you may need to restart the kernel to use updated packages.\n"
          ]
        }
      ],
      "source": [
        "%pip install --quiet -U langchain-google-genai"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 17,
      "metadata": {},
      "outputs": [],
      "source": [
        "from langchain_google_genai import ChatGoogleGenerativeAI\n",
        "\n",
        "llm: ChatGoogleGenerativeAI = ChatGoogleGenerativeAI(model=\"gemini-1.5-flash\", api_key=gemini_api_key)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 18,
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "content='Hi there! What can I do for you today? \\n' additional_kwargs={} response_metadata={'prompt_feedback': {'block_reason': 0, 'safety_ratings': []}, 'finish_reason': 'STOP', 'safety_ratings': [{'category': 'HARM_CATEGORY_SEXUALLY_EXPLICIT', 'probability': 'NEGLIGIBLE', 'blocked': False}, {'category': 'HARM_CATEGORY_HATE_SPEECH', 'probability': 'NEGLIGIBLE', 'blocked': False}, {'category': 'HARM_CATEGORY_HARASSMENT', 'probability': 'NEGLIGIBLE', 'blocked': False}, {'category': 'HARM_CATEGORY_DANGEROUS_CONTENT', 'probability': 'NEGLIGIBLE', 'blocked': False}]} id='run-0bfdfcef-c7ee-4939-a8f4-4fb0756330b6-0' usage_metadata={'input_tokens': 2, 'output_tokens': 12, 'total_tokens': 14}\n"
          ]
        }
      ],
      "source": [
        "simple_call = llm.invoke(\"Hi\")\n",
        "print(simple_call)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 19,
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "content=\"I am a large language model, trained by Google. I don't have a name. \\n\" additional_kwargs={} response_metadata={'prompt_feedback': {'block_reason': 0, 'safety_ratings': []}, 'finish_reason': 'STOP', 'safety_ratings': [{'category': 'HARM_CATEGORY_SEXUALLY_EXPLICIT', 'probability': 'NEGLIGIBLE', 'blocked': False}, {'category': 'HARM_CATEGORY_HATE_SPEECH', 'probability': 'NEGLIGIBLE', 'blocked': False}, {'category': 'HARM_CATEGORY_HARASSMENT', 'probability': 'NEGLIGIBLE', 'blocked': False}, {'category': 'HARM_CATEGORY_DANGEROUS_CONTENT', 'probability': 'NEGLIGIBLE', 'blocked': False}]} id='run-b87dc777-45c1-417c-9cce-5d23f78d88a5-0' usage_metadata={'input_tokens': 6, 'output_tokens': 20, 'total_tokens': 26}\n"
          ]
        }
      ],
      "source": [
        "messages = [HumanMessage(content=\"What is your name?\")]\n",
        "result = llm.invoke(messages)\n",
        "print(result)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 20,
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "content='Hi there! My name is Bob. 😊  How can I help you today? \\n' additional_kwargs={} response_metadata={'prompt_feedback': {'block_reason': 0, 'safety_ratings': []}, 'finish_reason': 'STOP', 'safety_ratings': [{'category': 'HARM_CATEGORY_SEXUALLY_EXPLICIT', 'probability': 'NEGLIGIBLE', 'blocked': False}, {'category': 'HARM_CATEGORY_HATE_SPEECH', 'probability': 'NEGLIGIBLE', 'blocked': False}, {'category': 'HARM_CATEGORY_HARASSMENT', 'probability': 'NEGLIGIBLE', 'blocked': False}, {'category': 'HARM_CATEGORY_DANGEROUS_CONTENT', 'probability': 'NEGLIGIBLE', 'blocked': False}]} id='run-4176d413-4e4b-4b37-a5df-45e436c0a6ff-0' usage_metadata={'input_tokens': 17, 'output_tokens': 17, 'total_tokens': 34}\n"
          ]
        }
      ],
      "source": [
        "system_human_message = [\n",
        "                SystemMessage(content=\"You are a helpful assistant! Your name is Bob.\"),\n",
        "                HumanMessage(content=\"What is your name?\")\n",
        "            ]\n",
        "result = llm.invoke(system_human_message)\n",
        "print(result)\n",
        "\n",
        " "
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 21,
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "content='I am a large language model, trained by Google.' additional_kwargs={} response_metadata={'prompt_feedback': {'block_reason': 0, 'safety_ratings': []}, 'finish_reason': 'STOP', 'safety_ratings': [{'category': 'HARM_CATEGORY_SEXUALLY_EXPLICIT', 'probability': 'NEGLIGIBLE', 'blocked': False}, {'category': 'HARM_CATEGORY_HATE_SPEECH', 'probability': 'NEGLIGIBLE', 'blocked': False}, {'category': 'HARM_CATEGORY_HARASSMENT', 'probability': 'NEGLIGIBLE', 'blocked': False}, {'category': 'HARM_CATEGORY_DANGEROUS_CONTENT', 'probability': 'NEGLIGIBLE', 'blocked': False}]} id='run-679795af-80ff-4fa9-a360-b594054bf104-0' usage_metadata={'input_tokens': 6, 'output_tokens': 11, 'total_tokens': 17}\n"
          ]
        }
      ],
      "source": [
        "context_call = llm.invoke(messages)\n",
        "print(context_call)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Tools\n",
        "\n",
        "Tools are useful whenever you want a model to interact with external systems.\n",
        "\n",
        "External systems (e.g., APIs) often require a particular input schema or payload, rather than natural language.\n",
        "\n",
        "When we bind an API, for example, as a tool we given the model awareness of the required input schema.\n",
        "\n",
        "The model will choose to call a tool based upon the natural language input from the user.\n",
        "\n",
        "And, it will return an output that adheres to the tool's schema.\n",
        "\n",
        "[Many LLM providers support tool calling](https://python.langchain.com/v0.1/docs/integrations/chat/) and [tool calling interface](https://blog.langchain.dev/improving-core-tool-interfaces-and-docs-in-langchain/) in LangChain is simple.\n",
        "\n",
        "You can simply pass any Python `function` into `ChatModel.bind_tools(function)`.\n",
        "\n",
        "![Screenshot 2024-08-19 at 7.46.28 PM.png](https://cdn.prod.website-files.com/65b8cd72835ceeacd4449a53/66dbab08dc1c17a7a57f9960_chain2.png)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 22,
      "metadata": {
        "id": "k0zSnHU4Kt82"
      },
      "outputs": [],
      "source": [
        "%%capture --no-stderr\n",
        "%pip install --quiet -U langchain-google-genai langchain_core langgraph"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "yQ7JAd3hKx7H"
      },
      "outputs": [],
      "source": [
        "from google.colab import userdata\n",
        "gemini_api_key = userdata.get('GEMINI_API_KEY')\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 23,
      "metadata": {
        "id": "wrQIRNgeKzAX"
      },
      "outputs": [],
      "source": [
        "from langchain_google_genai import ChatGoogleGenerativeAI\n",
        "\n",
        "llm: ChatGoogleGenerativeAI = ChatGoogleGenerativeAI(model=\"gemini-1.5-flash\", api_key=gemini_api_key)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "n-MwHYPdNGDm"
      },
      "source": [
        "## Tool Calling"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 24,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "aaY-4l3pK5Kt",
        "outputId": "32c2f21f-3301-4747-96b0-796096d9e470"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "\n",
            "\n",
            "llm\n",
            " model='models/gemini-1.5-flash' google_api_key=SecretStr('**********') client=<google.ai.generativelanguage_v1beta.services.generative_service.client.GenerativeServiceClient object at 0x127929bb0> async_client=<google.ai.generativelanguage_v1beta.services.generative_service.async_client.GenerativeServiceAsyncClient object at 0x127931d60> default_metadata=() \n",
            "\n",
            "\n",
            "\n"
          ]
        }
      ],
      "source": [
        "print(\"\\n\\nllm\\n\", llm, \"\\n\\n\\n\")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 25,
      "metadata": {
        "id": "V8CPSMndK1ie"
      },
      "outputs": [],
      "source": [
        "def deposit_money(name: str, bank_account_no: int) -> int:\n",
        "    \"\"\"Deposit Money in Bank account.\n",
        "\n",
        "    Args:\n",
        "        name: first str\n",
        "        bank_account_no: second int\n",
        "    \"\"\"\n",
        "    # BUSINESS LOGIC for Bank Deposit\n",
        "    # ......\n",
        "    return {\"status\": f\"Deposit Successfule in {name} Account\"}"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 26,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "6A3-xLJ6L5eI",
        "outputId": "30806d65-5607-44aa-91d8-6eaac928f67c"
      },
      "outputs": [
        {
          "name": "stderr",
          "output_type": "stream",
          "text": [
            "Key 'title' is not supported in schema, ignoring\n",
            "Key 'title' is not supported in schema, ignoring\n",
            "Key 'title' is not supported in schema, ignoring\n"
          ]
        }
      ],
      "source": [
        "llm_with_tools = llm.bind_tools([deposit_money])"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 27,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "4qLqBwVnL_Lt",
        "outputId": "49d89b8a-54a0-4e75-d5bc-14ab6133e118"
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "RunnableBinding(bound=ChatGoogleGenerativeAI(model='models/gemini-1.5-flash', google_api_key=SecretStr('**********'), client=<google.ai.generativelanguage_v1beta.services.generative_service.client.GenerativeServiceClient object at 0x127929bb0>, async_client=<google.ai.generativelanguage_v1beta.services.generative_service.async_client.GenerativeServiceAsyncClient object at 0x127931d60>, default_metadata=()), kwargs={'tools': [{'function_declarations': [{'name': 'deposit_money', 'description': 'Deposit Money in Bank account.\\n\\n    Args:\\n        name: first str\\n        bank_account_no: second int', 'parameters': {'type_': 6, 'description': 'Deposit Money in Bank account.\\n\\nArgs:\\n    name: first str\\n    bank_account_no: second int', 'properties': {'bank_account_no': {'type_': 3, 'format_': '', 'description': '', 'nullable': False, 'enum': [], 'properties': {}, 'required': []}, 'name': {'type_': 1, 'format_': '', 'description': '', 'nullable': False, 'enum': [], 'properties': {}, 'required': []}}, 'required': ['name', 'bank_account_no'], 'format_': '', 'nullable': False, 'enum': []}}]}], 'tool_config': None}, config={}, config_factories=[])"
            ]
          },
          "execution_count": 27,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "llm_with_tools"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 28,
      "metadata": {
        "id": "Zb1gQFn2LGYE"
      },
      "outputs": [],
      "source": [
        "from langchain_core.messages import HumanMessage"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 29,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "QRDkyI9CMMUs",
        "outputId": "7c05f947-52d6-40b2-966d-eec7f678529a"
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "AIMessage(content=\"I understand you want to deposit money into Ahmad's account. However, I am unable to do that. I am a language model and do not have access to real-world financial systems or personal accounts. \\n\\nTo deposit money into Ahmad's account, you will need to contact his bank or financial institution directly. They will need more information than just his account number, such as his full name and possibly other identifying information. \\n\\nPlease be aware that sharing personal financial information online is risky. It is always best to handle these matters through secure channels provided by your bank or financial institution. \\n\", additional_kwargs={}, response_metadata={'prompt_feedback': {'block_reason': 0, 'safety_ratings': []}, 'finish_reason': 'STOP', 'safety_ratings': [{'category': 'HARM_CATEGORY_SEXUALLY_EXPLICIT', 'probability': 'NEGLIGIBLE', 'blocked': False}, {'category': 'HARM_CATEGORY_HATE_SPEECH', 'probability': 'NEGLIGIBLE', 'blocked': False}, {'category': 'HARM_CATEGORY_HARASSMENT', 'probability': 'NEGLIGIBLE', 'blocked': False}, {'category': 'HARM_CATEGORY_DANGEROUS_CONTENT', 'probability': 'NEGLIGIBLE', 'blocked': False}]}, id='run-22bfd3a8-1bdc-48a7-8843-871d408195e8-0', usage_metadata={'input_tokens': 17, 'output_tokens': 120, 'total_tokens': 137})"
            ]
          },
          "execution_count": 29,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "call = llm.invoke(\n",
        "    [HumanMessage(content=f\"Deposit Money in Ahmad Account. His acc number is 00123\", name=\"Muhammad\")])\n",
        "call\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 30,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "FXfKvapxLAg_",
        "outputId": "87056c14-ae62-4563-a9f9-00bf3692cd4f"
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "AIMessage(content='', additional_kwargs={'function_call': {'name': 'deposit_money', 'arguments': '{\"bank_account_no\": 123.0, \"name\": \"Ahmad\"}'}}, response_metadata={'prompt_feedback': {'block_reason': 0, 'safety_ratings': []}, 'finish_reason': 'STOP', 'safety_ratings': [{'category': 'HARM_CATEGORY_HARASSMENT', 'probability': 'NEGLIGIBLE', 'blocked': False}, {'category': 'HARM_CATEGORY_HATE_SPEECH', 'probability': 'NEGLIGIBLE', 'blocked': False}, {'category': 'HARM_CATEGORY_SEXUALLY_EXPLICIT', 'probability': 'NEGLIGIBLE', 'blocked': False}, {'category': 'HARM_CATEGORY_DANGEROUS_CONTENT', 'probability': 'NEGLIGIBLE', 'blocked': False}]}, id='run-01a27487-4ef3-4525-8552-3545b2e9689b-0', tool_calls=[{'name': 'deposit_money', 'args': {'bank_account_no': 123.0, 'name': 'Ahmad'}, 'id': '38fc1423-1dca-46c5-a818-b38df999e339', 'type': 'tool_call'}], usage_metadata={'input_tokens': 94, 'output_tokens': 26, 'total_tokens': 120})"
            ]
          },
          "execution_count": 30,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "call = llm_with_tools.invoke(\n",
        "    [HumanMessage(content=f\"Deposit Money in Ahmad Account. His acc number is 00123\", name=\"Muhammad\")])\n",
        "call"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "uUV74OzmNRwK"
      },
      "source": [
        "### Building Graph"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 31,
      "metadata": {
        "id": "bwUSDpDRNTNu"
      },
      "outputs": [],
      "source": [
        "# We have an LLM Capable of Tool Calling: using bind_tools\n",
        "\n",
        "# Now Lets do the Orchestration Through LangGraph\n",
        "\n",
        "# 0.  State\n",
        "\n",
        "from typing_extensions import TypedDict\n",
        "\n",
        "class LlmWithToolSState(TypedDict):\n",
        "  messages: list\n",
        "\n",
        "# 1. tool calling llm ki Node\n",
        "\n",
        "def call_llm(state: LlmWithToolSState):\n",
        "  messages = state[\"messages\"]\n",
        "  call_response = llm_with_tools.invoke(messages)\n",
        "  # messages.append(call_response)\n",
        "\n",
        "  # return {\"messages\": messages}\n",
        "  return {\"messages\": [call_response]}\n",
        "\n",
        "# 2. Graph\n",
        "\n",
        "from langgraph.graph import StateGraph, START, END\n",
        "\n",
        "builder: StateGraph = StateGraph(LlmWithToolSState)\n",
        "\n",
        "# define nodes\n",
        "builder.add_node(\"call_llm_with_tools\", call_llm)\n",
        "\n",
        "# define edges\n",
        "builder.add_edge(START, \"call_llm_with_tools\")\n",
        "builder.add_edge(\"call_llm_with_tools\", END)\n",
        "\n",
        "# build graph\n",
        "graph = builder.compile()\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 32,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 251
        },
        "id": "0xqNUBlwPi4Y",
        "outputId": "6452cc6a-58a0-4371-9b5f-640c1ec4ae0e"
      },
      "outputs": [
        {
          "data": {
            "image/jpeg": "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",
            "text/plain": [
              "<IPython.core.display.Image object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "from IPython.display import display, Image\n",
        "\n",
        "display(Image(graph.get_graph().draw_mermaid_png()))"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 33,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "jPyDSV6FPqO-",
        "outputId": "3b3b3ae3-e4dd-4f1a-b18b-4cea33772c1a"
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "{'messages': [AIMessage(content='Hello! How can I help you today? \\n', additional_kwargs={}, response_metadata={'prompt_feedback': {'block_reason': 0, 'safety_ratings': []}, 'finish_reason': 'STOP', 'safety_ratings': [{'category': 'HARM_CATEGORY_SEXUALLY_EXPLICIT', 'probability': 'NEGLIGIBLE', 'blocked': False}, {'category': 'HARM_CATEGORY_HATE_SPEECH', 'probability': 'NEGLIGIBLE', 'blocked': False}, {'category': 'HARM_CATEGORY_HARASSMENT', 'probability': 'NEGLIGIBLE', 'blocked': False}, {'category': 'HARM_CATEGORY_DANGEROUS_CONTENT', 'probability': 'NEGLIGIBLE', 'blocked': False}]}, id='run-cc57069f-6a3e-4526-af39-b4fb8399c1d9-0', usage_metadata={'input_tokens': 79, 'output_tokens': 9, 'total_tokens': 88})]}"
            ]
          },
          "execution_count": 33,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "graph.invoke({\"messages\": [HumanMessage(content=\"Hi\")]})"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 34,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "d_Md3GjXP0yU",
        "outputId": "6d1f071f-7f6e-4f53-dae2-f2eda5409e55"
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "{'messages': [AIMessage(content='', additional_kwargs={'function_call': {'name': 'deposit_money', 'arguments': '{\"bank_account_no\": 1.0, \"name\": \"Ahmad\"}'}}, response_metadata={'prompt_feedback': {'block_reason': 0, 'safety_ratings': []}, 'finish_reason': 'STOP', 'safety_ratings': [{'category': 'HARM_CATEGORY_SEXUALLY_EXPLICIT', 'probability': 'NEGLIGIBLE', 'blocked': False}, {'category': 'HARM_CATEGORY_HATE_SPEECH', 'probability': 'NEGLIGIBLE', 'blocked': False}, {'category': 'HARM_CATEGORY_DANGEROUS_CONTENT', 'probability': 'NEGLIGIBLE', 'blocked': False}, {'category': 'HARM_CATEGORY_HARASSMENT', 'probability': 'NEGLIGIBLE', 'blocked': False}]}, id='run-97f74524-ff40-4957-847f-49602dd14140-0', tool_calls=[{'name': 'deposit_money', 'args': {'bank_account_no': 1.0, 'name': 'Ahmad'}, 'id': '66818e6d-f603-428f-9953-4c8645b44a2b', 'type': 'tool_call'}], usage_metadata={'input_tokens': 98, 'output_tokens': 24, 'total_tokens': 122})]}"
            ]
          },
          "execution_count": 34,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "graph.invoke({\"messages\": [HumanMessage(content=\"Deposiut 7000 in Ahmad Account - his bank num is 001\")]})"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "#### Current Flow \n",
        "\n",
        "- LLM: Call this Tool\n",
        "- System: Called Tool and told LLM the result.\n",
        "\n",
        "#### Issue ??: Where is my Human Message \n",
        "\n",
        "Right now in response we only have AIMessage\n",
        "\n",
        "#### Solutions:\n",
        "\n",
        "- Proposal 1: manually Add Messages in call_llm using llm\n",
        "- Proposal 2: Reducer Functions to Keep History Context"
      ]
    }
  ],
  "metadata": {
    "colab": {
      "provenance": []
    },
    "kernelspec": {
      "display_name": "Python 3",
      "name": "python3"
    },
    "language_info": {
      "codemirror_mode": {
        "name": "ipython",
        "version": 3
      },
      "file_extension": ".py",
      "mimetype": "text/x-python",
      "name": "python",
      "nbconvert_exporter": "python",
      "pygments_lexer": "ipython3",
      "version": "3.12.6"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}
